package com.itxixi.infrastructure.persistent.repository;

import com.itxixi.domain.strategy.model.entity.StrategyAwardEntity;
import com.itxixi.domain.strategy.model.entity.StrategyEntity;
import com.itxixi.domain.strategy.model.entity.StrategyRuleEntity;
import com.itxixi.domain.strategy.repository.IStrategyRepository;
import com.itxixi.infrastructure.persistent.dao.IStrategyAwardDao;
import com.itxixi.infrastructure.persistent.dao.IStrategyDao;
import com.itxixi.infrastructure.persistent.dao.IStrategyRuleDao;
import com.itxixi.infrastructure.persistent.po.Strategy;
import com.itxixi.infrastructure.persistent.po.StrategyAward;
import com.itxixi.infrastructure.persistent.po.StrategyRule;
import com.itxixi.infrastructure.persistent.redis.IRedisService;
import com.itxixi.types.common.Constants;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Pyx 2024/10/23
 * @description 策略仓储实现
 * @create 2024-10-23 下午6:05
 */
@Repository
public class StrategyRepository implements IStrategyRepository {

    @Resource
    private IStrategyAwardDao strategyAwardDao;

    @Resource
    private IStrategyDao strategyDao;

    @Resource
    private IStrategyRuleDao strategyRuleDao;

    @Resource
    private IRedisService redisService;

    @Override
    public List<StrategyAwardEntity> queryStrategyAwardList(Long strategyId) {
        //优先从缓存中获取 没有就从库中找 然后放入redis中
        String cacheKey = Constants.RedisKey.STRATEGY_AWARD_KEY + strategyId;

        //Entity是DO DTO 返回前端
        List<StrategyAwardEntity> strategyAwardEntities = redisService.getValue(cacheKey);
        if (null != strategyAwardEntities && !strategyAwardEntities.isEmpty()) return strategyAwardEntities;
        //缓存穿透 查数据库为空则将该key对应的value设置为空

        //从库中读取数据 PO数据持久化对象
        List<StrategyAward> strategyAwards = strategyAwardDao.queryStrategyAwardListByStrategyId(strategyId);

        //重新new一个DTO对象 循环接收查询的PO  PO2DTO
        strategyAwardEntities = new ArrayList<>(strategyAwards.size());
        for(StrategyAward strategyAward : strategyAwards) { // po : pos
            StrategyAwardEntity strategyAwardEntity = StrategyAwardEntity.builder()
                        .strategyId(strategyAward.getStrategyId())//PO2DO
                        .awardId(strategyAward.getAwardId())
                        .awardCount(strategyAward.getAwardCount())
                        .awardCountSurplus(strategyAward.getAwardCountSurplus())
                        .awardRate(strategyAward.getAwardRate())
                        .build();
            strategyAwardEntities.add(strategyAwardEntity);
        }
        redisService.setValue(cacheKey,strategyAwardEntities);//redis缓存DO对象
        return strategyAwardEntities; //这里是仓储实现，返回DO给domain层调用方

    }

    @Override//存范围和查找表  这里没有非空判断 会一直重新覆盖
    public void storeStrategyAwardSearchRateTables(String key, Integer rateRange, HashMap<Integer, Integer> shuffleStrategyAwardSearchRateTables) {
                          //1.存储概率范围            //这里的rateRange对应shuffleStrategyAwardSearchRateTables.size()
        redisService.setValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key, rateRange.intValue());
                    //会重新覆盖
        //2. 存储概率查找表 getMap HashMap 对应redis的hash  获取Redis中的hash对象 HashMap会乱序存储
        Map<Integer,Integer> cacheRateTable =redisService.getMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key);
        cacheRateTable.putAll(shuffleStrategyAwardSearchRateTables);
        //putAll 如果map不存在 Rmap懒加载 在put的时候才会在redis中创建hash的键
        //putAll 如果map存在  就会覆盖（旧的）与合并（新的）

    }

    @Override//1得到key对应的概率范围
    public int getRateRange(Long strategyId) {
//        return redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY +strategyId);
        //+ 操作符用于字符串连接，因此 strategyId 会自动被转换为字符串。
        // 具体来说，Java 会隐式调用 strategyId.toString() 方法，将 strategyId 变为字符串，
        // 并与 Constants.RedisKey.STRATEGY_RATE_RANGE_KEY 连接成一个完整的字符串。
        return getRateRange(String.valueOf(strategyId));
    }


    @Override
    public int getRateRange(String key) {
        return redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY +key);
    }

    @Override//2得到key对应的查找表中field为rateKey的value
    public Integer getStrategyAwardAssemble(String key, int rateKey) {                         //随机数
//        return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + strategyId, rateKey);
                                                                       // + strategyId 对应总的装配表
        return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key, rateKey);
    }                                                            // + strategyId_4000  对应4000的装配表
//-------------------------------------------------------------------------------------------------------------
    @Override //到IStrategyDao中根据strategyId查找Strategy实体  以得到rulemodel字段
    public StrategyEntity queryStrategyEntityByStrategyId(Long strategyId) {
        // 优先从缓存获取
        String cacheKey = Constants.RedisKey.STRATEGY_KEY + strategyId;
        StrategyEntity strategyEntity = redisService.getValue(cacheKey);
        if (null != strategyEntity) return strategyEntity;
                         //到IStrategyDao中根据strategyId查找Strategy实体  以得到rulemodel字段
        Strategy strategy = strategyDao.queryStrategyByStrategyId(strategyId);

        if (null == strategy) return StrategyEntity.builder().build();
                        //Strategy的PO2DO
        strategyEntity = StrategyEntity.builder()
                .strategyId(strategy.getStrategyId())
                .strategyDesc(strategy.getStrategyDesc())
                .ruleModels(strategy.getRuleModels())//rule_blacklist,rule_weight
                .build();
        redisService.setValue(cacheKey, strategyEntity);//redis的string类型对象  会被序列化为json字符串
        return strategyEntity;
    }

    @Override//没有redis
    public StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleModel) {

        StrategyRule strategyRuleReq = new StrategyRule();
        strategyRuleReq.setStrategyId(strategyId);
        strategyRuleReq.setRuleModel(ruleModel);

        //到IStrategyRuleDao 中根据StrategyRule对象  根据strategyId 以及 ruleWeight 得到ruleValue
        StrategyRule strategyRuleRes = strategyRuleDao.queryStrategyRule(strategyRuleReq);
        if (null == strategyRuleRes) return null;
                    //StrategyRule的po2do
        return StrategyRuleEntity.builder()
                .strategyId(strategyRuleRes.getStrategyId())
                .awardId(strategyRuleRes.getAwardId())
                .ruleType(strategyRuleRes.getRuleType())
                .ruleModel(strategyRuleRes.getRuleModel())
                .ruleValue(strategyRuleRes.getRuleValue())
                .ruleDesc(strategyRuleRes.getRuleDesc())
                .build();
    }

    @Override
    public String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel) {
        StrategyRule strategyRule = new StrategyRule();
        strategyRule.setStrategyId(strategyId);
        strategyRule.setAwardId(awardId);
        strategyRule.setRuleModel(ruleModel);
        return strategyRuleDao.queryStrategyRuleValue(strategyRule);
    }


}
